package xyz.hubery.model;

import lombok.Data;
import lombok.Getter;
import xyz.hubery.domain.Order;
import xyz.hubery.enums.OrderDirection;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 委托单记录账本
 */
@Data
public class OrderBooks {

    {
        initialize();
    }

    /**
     * 买入委托账单
     * key：价格   value：价格相同的委托单，按时间排序
     * 价格越高越前，时间越早越前
     */
    private TreeMap<BigDecimal, MergeOrder> buyLimitPrice;


    /**
     * 卖出委托账单
     * key：价格   value：价格相同的委托单，按时间排序
     * 价格越低越前，时间越早越前
     */
    private TreeMap<BigDecimal, MergeOrder> sellLimitPrice;

    /**
     * 交易的币种
     */
    @Getter
    private String symbol;

    /**
     * 交易币种的精度
     */
    private int coinScale;

    /**
     * 基币的精度
     */
    private int baseCoinScale;

    /**
     * 日期格式器
     */
    private SimpleDateFormat dateTimeFormat;

    /**
     * 买入的盘口数据
     */
    private TradePlate buyTradePlate;

    /**
     * 卖出的盘口数据
     */
    private TradePlate sellTradePlate;

    public OrderBooks() {}

    public OrderBooks(String symbol){
        this(symbol,4,4);
    }

    public OrderBooks(String symbol,int coinScale,int baseCoinScale) {
        this.symbol = symbol;
        this.coinScale = coinScale;
        this.baseCoinScale = baseCoinScale;
    }

    /**
     * 初始化队列
     */
    public void initialize() {
        this.buyLimitPrice = new TreeMap<BigDecimal,MergeOrder>((o1, o2) -> o2.compareTo(o1));

        this.sellLimitPrice = new TreeMap<BigDecimal,MergeOrder>(BigDecimal::compareTo);

        dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        buyTradePlate = new TradePlate(symbol,OrderDirection.BUY);
        sellTradePlate = new TradePlate(symbol,OrderDirection.SELL);
    }

    /**
     * 获取特定方向的交易队列
     */
    public TreeMap<BigDecimal,MergeOrder> getCurrentOrders(OrderDirection direction) {
        return direction == OrderDirection.BUY ? this.buyLimitPrice : this.sellLimitPrice;
    }

    /**
     * 获取特定方向的交易队列的迭代器
     */
    public Iterator<Map.Entry<BigDecimal,MergeOrder>> getCurrentOrdersIterator(OrderDirection direction) {
        TreeMap<BigDecimal,MergeOrder> map = direction == OrderDirection.BUY ? this.buyLimitPrice : this.sellLimitPrice;
        return map.entrySet().iterator();
    }

    /**
     * 添加订单到交易队列
     */
    public void addOrder(Order order) {
        TreeMap<BigDecimal, MergeOrder> currentOrders = getCurrentOrders(OrderDirection.getDirectionByCode(order.getOrderDirection()));
        MergeOrder mergeOrder = currentOrders.get(order.getPrice());
        if(mergeOrder == null){
            mergeOrder = new MergeOrder();
            currentOrders.put(order.getPrice(),mergeOrder);
        }
        mergeOrder.add(order);

        // 同时更新盘口数据
        if(order.getOrderDirection()==OrderDirection.BUY.getCode()) { // 买入盘
            buyTradePlate.add(order);
        }else{
            sellTradePlate.add(order);
        }
    }

    /**
     * 移除一个订单
     */
    public boolean cancelOrder(Order order) {
        boolean ok = false; // 是否删除成功
        TreeMap<BigDecimal, MergeOrder> currentOrders = getCurrentOrders(OrderDirection.getDirectionByCode(order.getOrderDirection()));
        MergeOrder mergeOrder = currentOrders.get(order.getPrice());
        if(mergeOrder == null ) {
            return false;
        }
        Iterator<Order> iterator = mergeOrder.iterator();
        while (iterator.hasNext()) {
            Order currentOrder = iterator.next();
            if(currentOrder.getOrderId().equals(order.getOrderId())){
                iterator.remove();
                ok = true;
                break;
            }
        }
        if(mergeOrder.size() == 0){ // 不存在对其那价格的交易
            currentOrders.remove(order.getPrice());
        }

        // 同时更新盘口数据
        if(order.getOrderDirection()==OrderDirection.BUY.getCode()) { // 买入盘
            if(order.getOrderStatus() == 2) { // 撤销状态
                buyTradePlate.remove(order,order.getVolume());
            }else{
                buyTradePlate.remove(order);
            }
        }else{
            if(order.getOrderStatus() == 2) { // 撤销状态
                sellTradePlate.remove(order,order.getVolume());
            }else{
                sellTradePlate.remove(order);
            }
        }
        return ok;
    }

    /**
     * 获取排在队列里的第一个元素
     */
    public Map.Entry<BigDecimal,MergeOrder> getBestSuitPriceMergeOrder(OrderDirection direction) {
        TreeMap<BigDecimal, MergeOrder> currentOrders = getCurrentOrders(direction);
        return currentOrders.firstEntry();
    }


}
